home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / PeepholeOptimizer.c < prev    next >
Text File  |  1994-12-28  |  36KB  |  936 lines

  1. /* PeepholeOptimizer.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define SHOW_ME_OPCODEREC  /* we need to see the contents of opcode records */
  31. #include "PeepholeOptimizer.h"
  32. #include "PcodeObject.h"
  33. #include "Memory.h"
  34. #include "FixedPoint.h"
  35. #include "FloatingPoint.h"
  36.  
  37.  
  38. /* this routine scans the entire code block to see if any branches are made */
  39. /* to any but the first instruction specified in the run of instructions. */
  40. /* Start points to the first instruction, Extent specifies the number of WORDS */
  41. /* (not instructions).  Branches MAY point to Prog[Start], however. */
  42. static MyBoolean        NoBranchToInterior(OpcodeRec* Prog, long Length,
  43.                                             long Start, long Extent)
  44.     {
  45.         long                            Scan;
  46.  
  47.         for (Scan = 0; Scan < Length; Scan += GetInstructionLength(Prog[Scan].Opcode))
  48.             {
  49.                 PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
  50.                 if ((Prog[Scan].Opcode == epBranchUnconditional)
  51.                     || (Prog[Scan].Opcode == epBranchIfZero)
  52.                     || (Prog[Scan].Opcode == epBranchIfNotZero))
  53.                     {
  54.                         /* branch operation detected, test index */
  55.                         PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  56.                         if ((Prog[Scan + 1].ImmediateInteger > Start)
  57.                             && (Prog[Scan + 1].ImmediateInteger < Start + Extent))
  58.                             {
  59.                                 /* branch to interior found, so return false. */
  60.                                 return False;
  61.                             }
  62.                     }
  63.             }
  64.         ERROR(Scan != Length,PRERR(ForceAbort,
  65.             "NoBranchToInterior:  internal instruction alignment error"));
  66.         return True;
  67.     }
  68.  
  69.  
  70. /* this routine eliminates the specified segment of code from the program */
  71. /* and updates all branches pointing to areas beyond it.  The new length */
  72. /* is returned.  it also disposes of any additional storage used by the */
  73. /* instructions being deleted */
  74. static long                    DropCodeSegment(OpcodeRec* Prog, long Length,
  75.                                             long Start, long Extent)
  76.     {
  77.         long                            Scan;
  78.  
  79.         /* sanity check */
  80.         ERROR(!NoBranchToInterior(Prog,Length,Start,Extent),
  81.             PRERR(ForceAbort,"DropCodeSegment:  branches to interior"));
  82.         /* first, patch up branches */
  83.         for (Scan = 0; Scan < Length; Scan += GetInstructionLength(Prog[Scan].Opcode))
  84.             {
  85.                 /* looking for branch instructions */
  86.                 PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
  87.                 if ((Prog[Scan].Opcode == epBranchUnconditional)
  88.                     || (Prog[Scan].Opcode == epBranchIfZero)
  89.                     || (Prog[Scan].Opcode == epBranchIfNotZero))
  90.                     {
  91.                         /* found a branch instruction.  does it need to be patched? */
  92.                         PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  93.                         if (Prog[Scan + 1].ImmediateInteger > Start)
  94.                             {
  95.                                 /* branch is beyond segment being dropped, so decrement it's address */
  96.                                 /* by the length of the segment */
  97.                                 Prog[Scan + 1].ImmediateInteger -= Extent;
  98.                             }
  99.                     }
  100.             }
  101.         ERROR(Scan != Length,PRERR(ForceAbort,
  102.             "DropCodeSegment:  internal instruction alignment error:  branch resolve phase"));
  103.         /* next, dispose of additional memory owned by the instructions that */
  104.         /* are being deleted */
  105.         for (Scan = Start; Scan < Start + Extent;
  106.             Scan += GetInstructionLength(Prog[Scan].Opcode))
  107.             {
  108.                 switch (Prog[Scan].Opcode)
  109.                     {
  110.                         case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
  111.                         case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
  112.                             PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  113.                             ReleasePtr(Prog[Scan + 1].ImmediateString);
  114.                             PRNGCHK(Prog,&(Prog[Scan + 2]),sizeof(Prog[Scan + 2]));
  115.                             ReleasePtr((char*)(Prog[Scan + 2].DataTypeArray));
  116.                             break;
  117.                         case epOperationBooleanEqual: /* <opcode> */
  118.                         case epOperationBooleanNotEqual:
  119.                         case epOperationBooleanAnd:
  120.                         case epOperationBooleanOr:
  121.                         case epOperationBooleanNot:
  122.                         case epOperationBooleanToInteger:
  123.                         case epOperationBooleanToFloat:
  124.                         case epOperationBooleanToDouble:
  125.                         case epOperationBooleanToFixed:
  126.                         case epOperationIntegerAdd:
  127.                         case epOperationIntegerSubtract:
  128.                         case epOperationIntegerNegation:
  129.                         case epOperationIntegerMultiply:
  130.                         case epOperationIntegerDivide:
  131.                         case epOperationIntegerModulo:
  132.                         case epOperationIntegerShiftLeft:
  133.                         case epOperationIntegerShiftRight:
  134.                         case epOperationIntegerGreaterThan:
  135.                         case epOperationIntegerLessThan:
  136.                         case epOperationIntegerGreaterThanOrEqual:
  137.                         case epOperationIntegerLessThanOrEqual:
  138.                         case epOperationIntegerEqual:
  139.                         case epOperationIntegerNotEqual:
  140.                         case epOperationIntegerAbs:
  141.                         case epOperationIntegerToBoolean:
  142.                         case epOperationIntegerToFloat:
  143.                         case epOperationIntegerToDouble:
  144.                         case epOperationIntegerToFixed:
  145.                         case epOperationFloatAdd:
  146.                         case epOperationFloatSubtract:
  147.                         case epOperationFloatNegation:
  148.                         case epOperationFloatMultiply:
  149.                         case epOperationFloatDivide:
  150.                         case epOperationFloatGreaterThan:
  151.                         case epOperationFloatLessThan:
  152.                         case epOperationFloatGreaterThanOrEqual:
  153.                         case epOperationFloatLessThanOrEqual:
  154.                         case epOperationFloatEqual:
  155.                         case epOperationFloatNotEqual:
  156.                         case epOperationFloatAbs:
  157.                         case epOperationFloatToBoolean:
  158.                         case epOperationFloatToInteger:
  159.                         case epOperationFloatToDouble:
  160.                         case epOperationFloatToFixed:
  161.                         case epOperationDoubleAdd:
  162.                         case epOperationDoubleSubtract:
  163.                         case epOperationDoubleNegation:
  164.                         case epOperationDoubleMultiply:
  165.                         case epOperationDoubleDivide:
  166.                         case epOperationDoubleGreaterThan:
  167.                         case epOperationDoubleLessThan:
  168.                         case epOperationDoubleGreaterThanOrEqual:
  169.                         case epOperationDoubleLessThanOrEqual:
  170.                         case epOperationDoubleEqual:
  171.                         case epOperationDoubleNotEqual:
  172.                         case epOperationDoubleAbs:
  173.                         case epOperationDoubleToBoolean:
  174.                         case epOperationDoubleToInteger:
  175.                         case epOperationDoubleToFloat:
  176.                         case epOperationDoubleToFixed:
  177.                         case epOperationDoubleSin:
  178.                         case epOperationDoubleCos:
  179.                         case epOperationDoubleTan:
  180.                         case epOperationDoubleAtan:
  181.                         case epOperationDoubleLn:
  182.                         case epOperationDoubleExp:
  183.                         case epOperationDoubleSqrt:
  184.                         case epOperationDoublePower:
  185.                         case epOperationFixedAdd:
  186.                         case epOperationFixedSubtract:
  187.                         case epOperationFixedNegation:
  188.                         case epOperationFixedMultiply:
  189.                         case epOperationFixedDivide:
  190.                         case epOperationFixedShiftLeft:
  191.                         case epOperationFixedShiftRight:
  192.                         case epOperationFixedGreaterThan:
  193.                         case epOperationFixedLessThan:
  194.                         case epOperationFixedGreaterThanOrEqual:
  195.                         case epOperationFixedLessThanOrEqual:
  196.                         case epOperationFixedEqual:
  197.                         case epOperationFixedNotEqual:
  198.                         case epOperationFixedAbs:
  199.                         case epOperationFixedToBoolean:
  200.                         case epOperationFixedToInteger:
  201.                         case epOperationFixedToFloat:
  202.                         case epOperationFixedToDouble:
  203.                         case epGetBooleanArraySize: /* <opcode> */
  204.                         case epGetIntegerArraySize:
  205.                         case epGetFloatArraySize:
  206.                         case epGetDoubleArraySize:
  207.                         case epGetFixedArraySize:
  208.                         case epReturnFromSubroutine: /* <opcode> */
  209.                         case epLoadImmediateNILArray: /* <opcode> */
  210.                         case epMakeBooleanArray: /* <opcode> */
  211.                         case epMakeIntegerArray:
  212.                         case epMakeFloatArray:
  213.                         case epMakeDoubleArray:
  214.                         case epMakeFixedArray:
  215.                         case epStackPop: /* <opcode> */
  216.                         case epDuplicate: /* <opcode> */
  217.                         case epNop: /* <opcode> */
  218.                         case epStackAllocate: /* <opcode> */
  219.                         case epResizeBooleanArray2: /* <opcode> */
  220.                         case epResizeIntegerArray2:
  221.                         case epResizeFloatArray2:
  222.                         case epResizeDoubleArray2:
  223.                         case epResizeFixedArray2:
  224.                         case epStoreBooleanIntoArray2: /* <opcode> */
  225.                         case epStoreIntegerIntoArray2:
  226.                         case epStoreFloatIntoArray2:
  227.                         case epStoreDoubleIntoArray2:
  228.                         case epStoreFixedIntoArray2:
  229.                         case epLoadBooleanFromArray2: /* <opcode> */
  230.                         case epLoadIntegerFromArray2:
  231.                         case epLoadFloatFromArray2:
  232.                         case epLoadDoubleFromArray2:
  233.                         case epLoadFixedFromArray2:
  234.                         case epOperationBooleanXor:
  235.                         case epOperationIntegerAnd:
  236.                         case epOperationFixedAnd:
  237.                         case epOperationIntegerOr:
  238.                         case epOperationFixedOr:
  239.                         case epOperationIntegerXor:
  240.                         case epOperationFixedXor:
  241.                         case epOperationIntegerImpreciseDivide:
  242.                         case epOperationFloatShiftLeft:
  243.                         case epOperationDoubleShiftLeft:
  244.                         case epOperationFloatShiftRight:
  245.                         case epOperationDoubleShiftRight:
  246.                         case epOperationIntegerNot:
  247.                         case epOperationDoubleAsin:
  248.                         case epOperationDoubleAcos:
  249.                         case epOperationDoubleSqr:
  250.                         case epOperationTestIntegerNegative:
  251.                         case epOperationTestFloatNegative:
  252.                         case epOperationTestDoubleNegative:
  253.                         case epOperationTestFixedNegative:
  254.                         case epOperationGetSignInteger:
  255.                         case epOperationGetSignFloat:
  256.                         case epOperationGetSignDouble:
  257.                         case epOperationGetSignFixed:
  258.                         case epStackPopMultiple: /* <opcode> <numwords> */
  259.                         case epStackDeallocateUnder: /* <opcode> <numwords> */
  260.                         case epOperationBooleanToIntegerBuried:  /* <opcode> <stackindex> */
  261.                         case epOperationBooleanToFloatBuried:
  262.                         case epOperationBooleanToDoubleBuried:
  263.                         case epOperationBooleanToFixedBuried:
  264.                         case epOperationIntegerToBooleanBuried:
  265.                         case epOperationIntegerToFloatBuried:
  266.                         case epOperationIntegerToDoubleBuried:
  267.                         case epOperationIntegerToFixedBuried:
  268.                         case epOperationFloatToBooleanBuried:
  269.                         case epOperationFloatToIntegerBuried:
  270.                         case epOperationFloatToDoubleBuried:
  271.                         case epOperationFloatToFixedBuried:
  272.                         case epOperationDoubleToBooleanBuried:
  273.                         case epOperationDoubleToIntegerBuried:
  274.                         case epOperationDoubleToFloatBuried:
  275.                         case epOperationDoubleToFixedBuried:
  276.                         case epOperationFixedToBooleanBuried:
  277.                         case epOperationFixedToIntegerBuried:
  278.                         case epOperationFixedToFloatBuried:
  279.                         case epOperationFixedToDoubleBuried:
  280.                         case epBranchUnconditional: /* <opcode> <branchoffset> */
  281.                         case epBranchIfZero:
  282.                         case epBranchIfNotZero:
  283.                         case epStoreIntegerOnStack: /* <opcode> <stackindex> */
  284.                         case epStoreFloatOnStack:
  285.                         case epStoreDoubleOnStack:
  286.                         case epStoreArrayOnStack:
  287.                         case epLoadIntegerFromStack:
  288.                         case epLoadFloatFromStack:
  289.                         case epLoadDoubleFromStack:
  290.                         case epLoadArrayFromStack:
  291.                         case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
  292.                             break;
  293.                         case epLoadImmediateFloat: /* <opcode> ^<float> */
  294.                             PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  295.                             ReleasePtr((char*)(Prog[Scan + 1].ImmediateFloat));
  296.                             break;
  297.                         case epLoadImmediateDouble: /* <opcode> ^<double> */
  298.                             PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  299.                             ReleasePtr((char*)(Prog[Scan + 1].ImmediateDouble));
  300.                             break;
  301.                         case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
  302.                         case epGetSampleRightArray:
  303.                         case epGetSampleMonoArray:
  304.                             PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  305.                             ReleasePtr((char*)(Prog[Scan + 1].ImmediateString));
  306.                             break;
  307.                         case epErrorTrap: /* <opcode> ^"<errorstring>" */
  308.                             PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
  309.                             ReleasePtr(Prog[Scan + 1].ImmediateString);
  310.                             break;
  311.                         default:
  312.                             EXECUTE(PRERR(ForceAbort,"DropCodeSegment:  unknown opcode"));
  313.                     }
  314.             }
  315.         ERROR(Scan != Start + Extent,PRERR(ForceAbort,
  316.             "DropCodeSegment:  internal instruction alignment error:  dispose phase"));
  317.         /* now, delete the code segment */
  318.         for (Scan = Start; Scan < Length - Extent; Scan += 1)
  319.             {
  320.                 PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
  321.                 PRNGCHK(Prog,&(Prog[Scan + Extent]),sizeof(Prog[Scan + Extent]));
  322.                 Prog[Scan] = Prog[Scan + Extent];
  323.             }
  324.         /* now, erase that little bit at the end */
  325.         for (Scan = Length - Extent; Scan < Length; Scan += 1)
  326.             {
  327.                 PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
  328.                 Prog[Scan].Opcode = epNop;
  329.             }
  330.         /* now, return the new code length */
  331.         return Length - Extent;
  332.     }
  333.  
  334.  
  335. /* this routine looks for indivisible dup/pop operations (with no interior */
  336. /* branches) and eliminates them.  *Flag is set if some change was made, and the */
  337. /* new length of Prog[] is returned. */
  338. static long                    EliminateDupPop(OpcodeRec* Prog, long Length, MyBoolean* Flag)
  339.     {
  340.         long                            Scan;
  341.  
  342.         Scan = 0;
  343.         while (Scan < Length)
  344.             {
  345.                 /* look to see if this part can be dropped.  if it can, we don't increment */
  346.                 /* Scan so that we can look at the part that will be moved into where this */
  347.                 /* is as well.  otherwise, we do increment */
  348.                 if ((Prog[Scan].Opcode == epDuplicate)
  349.                     && (Prog[Scan + 1].Opcode == epStackPop)
  350.                     && NoBranchToInterior(Prog,Length,Scan,2))
  351.                     {
  352.                         /* found one! */
  353.                         Length = DropCodeSegment(Prog,Length,Scan,2);
  354.                         *Flag = True;
  355.                     }
  356.                  else
  357.                     {
  358.                         /* increment only if not found */
  359.                         Scan += GetInstructionLength(Prog[Scan].Opcode);
  360.                     }
  361.             }
  362.         ERROR(Scan != Length,PRERR(ForceAbort,
  363.             "EliminateDupPop:  internal instruction alignment error"));
  364.         return Length;
  365.     }
  366.  
  367.  
  368. /* this routine looks for constant operations that can be eliminated.  *Flag is */
  369. /* set if some change was made, and the new length of Prog[] is returned. */
  370. static long                    FoldConstants(OpcodeRec* Prog, long Length, MyBoolean* Flag)
  371.     {
  372.         long                            Scan;
  373.  
  374.         Scan = 0;
  375.         while (Scan < Length)
  376.             {
  377.                 MyBoolean                    DidSomething = False;
  378.  
  379.                 /* look to see if this part can be folded.  if it can, we don't increment */
  380.                 /* Scan so that we can look at the part that will be moved into where this */
  381.                 /* is as well.  otherwise, we do increment */
  382.                 switch (Prog[Scan].Opcode)
  383.                     {
  384.                         default:
  385.                             break;
  386.  
  387.                         case epLoadImmediateInteger: /*  <opcode> <integer> */
  388.                             if ((Scan + 2 < Length)
  389.                                 && NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
  390.                                 {
  391.                                     switch (Prog[Scan + 2].Opcode)
  392.                                         {
  393.                                             default:
  394.                                                 break;
  395.                                             case epOperationBooleanToInteger:
  396.                                                 /* no operation, remove */
  397.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  398.                                                 DidSomething = True;
  399.                                                 *Flag = True;
  400.                                                 break;
  401.                                             case epOperationIntegerToBoolean:
  402.                                             case epOperationFixedToBoolean:
  403.                                                 Prog[Scan + 1].ImmediateInteger =
  404.                                                     (Prog[Scan + 1].ImmediateInteger != 0);
  405.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  406.                                                 DidSomething = True;
  407.                                                 *Flag = True;
  408.                                                 break;
  409.                                             case epOperationBooleanNot:
  410.                                                 Prog[Scan + 1].ImmediateInteger =
  411.                                                     !Prog[Scan + 1].ImmediateInteger;
  412.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  413.                                                 DidSomething = True;
  414.                                                 *Flag = True;
  415.                                                 break;
  416.                                             case epOperationBooleanToFloat:
  417.                                             case epOperationIntegerToFloat:
  418.                                                 {
  419.                                                     float*                        FloatConst;
  420.  
  421.                                                     FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
  422.                                                     if (FloatConst != NIL)
  423.                                                         {
  424.                                                             /* convert int const to float */
  425.                                                             *FloatConst = Prog[Scan + 1].ImmediateInteger;
  426.                                                             Prog[Scan + 1].ImmediateFloat = FloatConst;
  427.                                                             /* change opcode */
  428.                                                             Prog[Scan].Opcode = epLoadImmediateFloat;
  429.                                                             /* delete opcode after it */
  430.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  431.                                                             DidSomething = True;
  432.                                                             *Flag = True;
  433.                                                         }
  434.                                                 }
  435.                                                 break;
  436.                                             case epOperationBooleanToDouble:
  437.                                             case epOperationIntegerToDouble:
  438.                                                 {
  439.                                                     double*                        DoubleConst;
  440.  
  441.                                                     DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
  442.                                                     if (DoubleConst != NIL)
  443.                                                         {
  444.                                                             /* convert int const to float */
  445.                                                             *DoubleConst = Prog[Scan + 1].ImmediateInteger;
  446.                                                             Prog[Scan + 1].ImmediateDouble = DoubleConst;
  447.                                                             /* change opcode */
  448.                                                             Prog[Scan].Opcode = epLoadImmediateDouble;
  449.                                                             /* delete opcode after it */
  450.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  451.                                                             DidSomething = True;
  452.                                                             *Flag = True;
  453.                                                         }
  454.                                                 }
  455.                                                 break;
  456.                                             case epOperationIntegerNegation:
  457.                                             case epOperationFixedNegation:
  458.                                                 Prog[Scan + 1].ImmediateInteger =
  459.                                                     - Prog[Scan + 1].ImmediateInteger;
  460.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  461.                                                 DidSomething = True;
  462.                                                 *Flag = True;
  463.                                                 break;
  464.                                             case epOperationIntegerAbs:
  465.                                             case epOperationFixedAbs:
  466.                                                 if (Prog[Scan + 1].ImmediateInteger < 0)
  467.                                                     {
  468.                                                         Prog[Scan + 1].ImmediateInteger =
  469.                                                             - Prog[Scan + 1].ImmediateInteger;
  470.                                                     }
  471.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  472.                                                 DidSomething = True;
  473.                                                 *Flag = True;
  474.                                                 break;
  475.                                             case epOperationIntegerToFixed:
  476.                                             case epOperationBooleanToFixed:
  477.                                                 Prog[Scan + 1].ImmediateInteger =
  478.                                                     int2largefixed(Prog[Scan + 1].ImmediateInteger);
  479.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  480.                                                 DidSomething = True;
  481.                                                 *Flag = True;
  482.                                                 break;
  483.                                             case epOperationIntegerNot:
  484.                                                 Prog[Scan + 1].ImmediateInteger =
  485.                                                     ~Prog[Scan + 1].ImmediateInteger;
  486.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  487.                                                 DidSomething = True;
  488.                                                 *Flag = True;
  489.                                                 break;
  490.                                             case epOperationTestIntegerNegative:
  491.                                             case epOperationTestFixedNegative:
  492.                                                 Prog[Scan + 1].ImmediateInteger =
  493.                                                     (Prog[Scan + 1].ImmediateInteger < 0);
  494.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  495.                                                 DidSomething = True;
  496.                                                 *Flag = True;
  497.                                                 break;
  498.                                             case epOperationGetSignInteger:
  499.                                             case epOperationGetSignFixed:
  500.                                                 if (Prog[Scan + 1].ImmediateInteger < 0)
  501.                                                     {
  502.                                                         Prog[Scan + 1].ImmediateInteger = -1;
  503.                                                     }
  504.                                                 else if (Prog[Scan + 1].ImmediateInteger > 0)
  505.                                                     {
  506.                                                         Prog[Scan + 1].ImmediateInteger = 1;
  507.                                                     }
  508.                                                 else
  509.                                                     {
  510.                                                         Prog[Scan + 1].ImmediateInteger = 0;
  511.                                                     }
  512.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  513.                                                 DidSomething = True;
  514.                                                 *Flag = True;
  515.                                                 break;
  516.                                             case epOperationFixedToInteger:
  517.                                                 Prog[Scan + 1].ImmediateInteger
  518.                                                     = largefixed2int(Prog[Scan + 1].ImmediateInteger);
  519.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  520.                                                 DidSomething = True;
  521.                                                 *Flag = True;
  522.                                                 break;
  523.                                             case epOperationFixedToFloat:
  524.                                                 {
  525.                                                     float*                        FloatConst;
  526.  
  527.                                                     FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
  528.                                                     if (FloatConst != NIL)
  529.                                                         {
  530.                                                             /* convert int const to float */
  531.                                                             *FloatConst = largefixed2double(Prog[Scan + 1].ImmediateInteger);
  532.                                                             Prog[Scan + 1].ImmediateFloat = FloatConst;
  533.                                                             /* change opcode */
  534.                                                             Prog[Scan].Opcode = epLoadImmediateFloat;
  535.                                                             /* delete opcode after it */
  536.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  537.                                                             DidSomething = True;
  538.                                                             *Flag = True;
  539.                                                         }
  540.                                                 }
  541.                                                 break;
  542.                                             case epOperationFixedToDouble:
  543.                                                 {
  544.                                                     double*                        DoubleConst;
  545.  
  546.                                                     DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
  547.                                                     if (DoubleConst != NIL)
  548.                                                         {
  549.                                                             /* convert int const to float */
  550.                                                             *DoubleConst = largefixed2double(Prog[Scan + 1].ImmediateInteger);
  551.                                                             Prog[Scan + 1].ImmediateDouble = DoubleConst;
  552.                                                             /* change opcode */
  553.                                                             Prog[Scan].Opcode = epLoadImmediateDouble;
  554.                                                             /* delete opcode after it */
  555.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  556.                                                             DidSomething = True;
  557.                                                             *Flag = True;
  558.                                                         }
  559.                                                 }
  560.                                                 break;
  561.                                         }
  562.                                 }
  563.                             break;
  564.  
  565.                         case epLoadImmediateFloat: /* <opcode> ^<float> */
  566.                             if ((Scan + 2 < Length)
  567.                                 && NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
  568.                                 {
  569.                                     switch (Prog[Scan + 2].Opcode)
  570.                                         {
  571.                                             default:
  572.                                                 break;
  573.                                             case epOperationFloatNegation:
  574.                                                 *(Prog[Scan + 1].ImmediateFloat) =
  575.                                                     - *(Prog[Scan + 1].ImmediateFloat);
  576.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  577.                                                 DidSomething = True;
  578.                                                 *Flag = True;
  579.                                                 break;
  580.                                             case epOperationFloatAbs:
  581.                                                 if (*(Prog[Scan + 1].ImmediateFloat) < 0)
  582.                                                     {
  583.                                                         *(Prog[Scan + 1].ImmediateFloat) =
  584.                                                             - *(Prog[Scan + 1].ImmediateFloat);
  585.                                                     }
  586.                                                 Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  587.                                                 DidSomething = True;
  588.                                                 *Flag = True;
  589.                                                 break;
  590.                                             case epOperationFloatToBoolean:
  591.                                                 {
  592.                                                     MyBoolean                    NewValue;
  593.  
  594.                                                     NewValue = (*(Prog[Scan + 1].ImmediateFloat) != 0);
  595.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  596.                                                     Prog[Scan + 1].ImmediateInteger = NewValue;
  597.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  598.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  599.                                                     DidSomething = True;
  600.                                                     *Flag = True;
  601.                                                 }
  602.                                                 break;
  603.                                             case epOperationFloatToInteger:
  604.                                                 {
  605.                                                     float                            TempValue;
  606.  
  607.                                                     TempValue = *(Prog[Scan + 1].ImmediateFloat);
  608.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  609.                                                     Prog[Scan + 1].ImmediateInteger = TempValue;
  610.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  611.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  612.                                                     DidSomething = True;
  613.                                                     *Flag = True;
  614.                                                 }
  615.                                                 break;
  616.                                             case epOperationFloatToDouble:
  617.                                                 {
  618.                                                     double*                        DoubleConst;
  619.  
  620.                                                     DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
  621.                                                     if (DoubleConst != NIL)
  622.                                                         {
  623.                                                             /* convert int const to float */
  624.                                                             *DoubleConst = *(Prog[Scan + 1].ImmediateFloat);
  625.                                                             ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  626.                                                             Prog[Scan + 1].ImmediateDouble = DoubleConst;
  627.                                                             /* change opcode */
  628.                                                             Prog[Scan].Opcode = epLoadImmediateDouble;
  629.                                                             /* delete opcode after it */
  630.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  631.                                                             DidSomething = True;
  632.                                                             *Flag = True;
  633.                                                         }
  634.                                                 }
  635.                                                 break;
  636.                                             case epOperationFloatToFixed:
  637.                                                 {
  638.                                                     float                            TempValue;
  639.  
  640.                                                     TempValue = *(Prog[Scan + 1].ImmediateFloat);
  641.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  642.                                                     Prog[Scan + 1].ImmediateInteger = double2largefixed(TempValue);
  643.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  644.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  645.                                                     DidSomething = True;
  646.                                                     *Flag = True;
  647.                                                 }
  648.                                                 break;
  649.                                             case epOperationGetSignFloat:
  650.                                                 {
  651.                                                     float                            TempValue;
  652.  
  653.                                                     TempValue = *(Prog[Scan + 1].ImmediateFloat);
  654.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  655.                                                     if (TempValue < 0)
  656.                                                         {
  657.                                                             Prog[Scan + 1].ImmediateInteger = -1;
  658.                                                         }
  659.                                                     else if (TempValue > 0)
  660.                                                         {
  661.                                                             Prog[Scan + 1].ImmediateInteger = 1;
  662.                                                         }
  663.                                                     else
  664.                                                         {
  665.                                                             Prog[Scan + 1].ImmediateInteger = 0;
  666.                                                         }
  667.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  668.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  669.                                                     DidSomething = True;
  670.                                                     *Flag = True;
  671.                                                 }
  672.                                                 break;
  673.                                             case epOperationTestFloatNegative:
  674.                                                 {
  675.                                                     float                            TempValue;
  676.  
  677.                                                     TempValue = *(Prog[Scan + 1].ImmediateFloat);
  678.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
  679.                                                     Prog[Scan + 1].ImmediateInteger = (TempValue < 0);
  680.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  681.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  682.                                                     DidSomething = True;
  683.                                                     *Flag = True;
  684.                                                 }
  685.                                                 break;
  686.                                         }
  687.                                 }
  688.                             break;
  689.  
  690.                         case epLoadImmediateDouble: /* <opcode> ^<double> */
  691.                             if ((Scan + 2 < Length)
  692.                                 && NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
  693.                                 {
  694.                                     switch (Prog[Scan + 2].Opcode)
  695.                                         {
  696.                                             default:
  697.                                                 break;
  698.                                             case epOperationDoubleNegation:
  699.                                                 *(Prog[Scan + 1].ImmediateDouble)
  700.                                                     = - *(Prog[Scan + 1].ImmediateDouble);
  701.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  702.                                                 DidSomething = True;
  703.                                                 *Flag = True;
  704.                                                 break;
  705.                                             case epOperationDoubleAbs:
  706.                                                 if (*(Prog[Scan + 1].ImmediateDouble) < 0)
  707.                                                     {
  708.                                                         *(Prog[Scan + 1].ImmediateDouble)
  709.                                                             = - *(Prog[Scan + 1].ImmediateDouble);
  710.                                                     }
  711.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  712.                                                 DidSomething = True;
  713.                                                 *Flag = True;
  714.                                                 break;
  715.                                             case epOperationDoubleToBoolean:
  716.                                                 {
  717.                                                     MyBoolean                    NewValue;
  718.  
  719.                                                     NewValue = (*(Prog[Scan + 1].ImmediateDouble) != 0);
  720.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  721.                                                     Prog[Scan + 1].ImmediateInteger = NewValue;
  722.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  723.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  724.                                                     DidSomething = True;
  725.                                                     *Flag = True;
  726.                                                 }
  727.                                                 break;
  728.                                             case epOperationDoubleToInteger:
  729.                                                 {
  730.                                                     double                        TempValue;
  731.  
  732.                                                     TempValue = *(Prog[Scan + 1].ImmediateDouble);
  733.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  734.                                                     Prog[Scan + 1].ImmediateInteger = TempValue;
  735.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  736.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  737.                                                     DidSomething = True;
  738.                                                     *Flag = True;
  739.                                                 }
  740.                                                 break;
  741.                                             case epOperationDoubleToFloat:
  742.                                                 {
  743.                                                     float*                        FloatConst;
  744.  
  745.                                                     FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
  746.                                                     if (FloatConst != NIL)
  747.                                                         {
  748.                                                             /* convert int const to float */
  749.                                                             *FloatConst = *(Prog[Scan + 1].ImmediateDouble);
  750.                                                             ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  751.                                                             Prog[Scan + 1].ImmediateFloat = FloatConst;
  752.                                                             /* change opcode */
  753.                                                             Prog[Scan].Opcode = epLoadImmediateFloat;
  754.                                                             /* delete opcode after it */
  755.                                                             Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  756.                                                             DidSomething = True;
  757.                                                             *Flag = True;
  758.                                                         }
  759.                                                 }
  760.                                                 break;
  761.                                             case epOperationDoubleToFixed:
  762.                                                 {
  763.                                                     double                        TempValue;
  764.  
  765.                                                     TempValue = *(Prog[Scan + 1].ImmediateDouble);
  766.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  767.                                                     Prog[Scan + 1].ImmediateInteger = double2largefixed(TempValue);
  768.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  769.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  770.                                                     DidSomething = True;
  771.                                                     *Flag = True;
  772.                                                 }
  773.                                                 break;
  774.                                             case epOperationDoubleSin:
  775.                                                 *(Prog[Scan + 1].ImmediateDouble)
  776.                                                     = DSIN(*(Prog[Scan + 1].ImmediateDouble));
  777.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  778.                                                 DidSomething = True;
  779.                                                 *Flag = True;
  780.                                                 break;
  781.                                             case epOperationDoubleCos:
  782.                                                 *(Prog[Scan + 1].ImmediateDouble)
  783.                                                     = DCOS(*(Prog[Scan + 1].ImmediateDouble));
  784.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  785.                                                 DidSomething = True;
  786.                                                 *Flag = True;
  787.                                                 break;
  788.                                             case epOperationDoubleTan:
  789.                                                 *(Prog[Scan + 1].ImmediateDouble)
  790.                                                     = DTAN(*(Prog[Scan + 1].ImmediateDouble));
  791.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  792.                                                 DidSomething = True;
  793.                                                 *Flag = True;
  794.                                                 break;
  795.                                             case epOperationDoubleAsin:
  796.                                                 *(Prog[Scan + 1].ImmediateDouble)
  797.                                                     = DASIN(*(Prog[Scan + 1].ImmediateDouble));
  798.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  799.                                                 DidSomething = True;
  800.                                                 *Flag = True;
  801.                                                 break;
  802.                                             case epOperationDoubleAcos:
  803.                                                 *(Prog[Scan + 1].ImmediateDouble)
  804.                                                     = DACOS(*(Prog[Scan + 1].ImmediateDouble));
  805.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  806.                                                 DidSomething = True;
  807.                                                 *Flag = True;
  808.                                                 break;
  809.                                             case epOperationDoubleAtan:
  810.                                                 *(Prog[Scan + 1].ImmediateDouble)
  811.                                                     = DATAN(*(Prog[Scan + 1].ImmediateDouble));
  812.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  813.                                                 DidSomething = True;
  814.                                                 *Flag = True;
  815.                                                 break;
  816.                                             case epOperationDoubleLn:
  817.                                                 *(Prog[Scan + 1].ImmediateDouble)
  818.                                                     = DLN(*(Prog[Scan + 1].ImmediateDouble));
  819.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  820.                                                 DidSomething = True;
  821.                                                 *Flag = True;
  822.                                                 break;
  823.                                             case epOperationDoubleExp:
  824.                                                 *(Prog[Scan + 1].ImmediateDouble)
  825.                                                     = DEXP(*(Prog[Scan + 1].ImmediateDouble));
  826.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  827.                                                 DidSomething = True;
  828.                                                 *Flag = True;
  829.                                                 break;
  830.                                             case epOperationDoubleSqrt:
  831.                                                 *(Prog[Scan + 1].ImmediateDouble)
  832.                                                     = DSQRT(*(Prog[Scan + 1].ImmediateDouble));
  833.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  834.                                                 DidSomething = True;
  835.                                                 *Flag = True;
  836.                                                 break;
  837.                                             case epOperationDoubleSqr:
  838.                                                 *(Prog[Scan + 1].ImmediateDouble)
  839.                                                     = (*(Prog[Scan + 1].ImmediateDouble))
  840.                                                     * (*(Prog[Scan + 1].ImmediateDouble));
  841.                                                  Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  842.                                                 DidSomething = True;
  843.                                                 *Flag = True;
  844.                                                 break;
  845.                                             case epOperationTestDoubleNegative:
  846.                                                 {
  847.                                                     double                        TempValue;
  848.  
  849.                                                     TempValue = *(Prog[Scan + 1].ImmediateDouble);
  850.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  851.                                                     Prog[Scan + 1].ImmediateInteger = (TempValue < 0);
  852.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  853.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  854.                                                     DidSomething = True;
  855.                                                     *Flag = True;
  856.                                                 }
  857.                                                 break;
  858.                                             case epOperationGetSignDouble:
  859.                                                 {
  860.                                                     double                        TempValue;
  861.  
  862.                                                     TempValue = *(Prog[Scan + 1].ImmediateDouble);
  863.                                                     ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
  864.                                                     if (TempValue < 0)
  865.                                                         {
  866.                                                             Prog[Scan + 1].ImmediateInteger = -1;
  867.                                                         }
  868.                                                     else if (TempValue > 0)
  869.                                                         {
  870.                                                             Prog[Scan + 1].ImmediateInteger = 1;
  871.                                                         }
  872.                                                     else
  873.                                                         {
  874.                                                             Prog[Scan + 1].ImmediateInteger = 0;
  875.                                                         }
  876.                                                     Prog[Scan].Opcode = epLoadImmediateInteger;
  877.                                                     Length = DropCodeSegment(Prog,Length,Scan + 2,1);
  878.                                                     DidSomething = True;
  879.                                                     *Flag = True;
  880.                                                 }
  881.                                                 break;
  882.                                         }
  883.                                 }
  884.                             break;
  885.                     }
  886.  
  887.                 if (!DidSomething)
  888.                     {
  889.                         /* increment only if not found */
  890.                         Scan += GetInstructionLength(Prog[Scan].Opcode);
  891.                     }
  892.             }
  893.         ERROR(Scan != Length,PRERR(ForceAbort,
  894.             "FoldConstants:  internal instruction alignment error"));
  895.         return Length;
  896.     }
  897.  
  898.  
  899. /* perform the optimizations */
  900. void                                OptimizePcode(PcodeRec* ThePcode)
  901.     {
  902.         OpcodeRec*                Prog;
  903.         long                            Length;
  904.         MyBoolean                    OptimizationFound;
  905.  
  906.         /* obtain the important information */
  907.         Prog = GetOpcodeFromPcode(ThePcode);
  908.         Length = GetNumberOfValidCellsInPcode(ThePcode);
  909.  
  910.         /* begin the optimization loop */
  911.         do
  912.             {
  913.                 /* we go until no more optimizations can be found, so we clear this */
  914.                 /* flag.  at the end, if the flag is set, we'll check again. */
  915.                 OptimizationFound = False;
  916.                 Length = EliminateDupPop(Prog,Length,&OptimizationFound);
  917.                 Length = FoldConstants(Prog,Length,&OptimizationFound);
  918.             } while (OptimizationFound);
  919.  
  920.         /* resize the code block to eliminate any empty cells at the end */
  921.         if (PtrSize((char*)Prog) != Length * sizeof(OpcodeRec))
  922.             {
  923.                 OpcodeRec*                Temp;
  924.  
  925.                 Temp = (OpcodeRec*)ResizePtr((char*)Prog,Length * sizeof(OpcodeRec));
  926.                 if (Temp != NIL)
  927.                     {
  928.                         UpdateOpcodeInPcode(ThePcode,Temp,Length);
  929.                     }
  930.                 /* if we couldn't resize it, then it's just too bad.  the evaluator */
  931.                 /* doesn't really depend on the length of the opcode for anything, so */
  932.                 /* it doesn't matter.  (DisposePcode does, but the end is erased with */
  933.                 /* nops, so it shouldn't delete anything important.) */
  934.             }
  935.     }
  936.